/*   This file is part of Super Luigi Bros.
 *
 *   Super Luigi Bros is free software: you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation, either version 3 of the License, or
 *   (at your option) any later version.
 *
 *   Super Luigi Bros is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with Super Luigi Bros.  If not, see <http://www.gnu.org/licenses/>.
 */
package luigibros.data.zip;

import java.awt.Image;
import java.awt.image.ImageObserver;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import luigibros.data.ImageStore;
import luigibros.data.xml.level.ImageMap;
import luigibros.data.xml.level.ImageMap.SpriteRecord;
import luigibros.util.LazyList;
/** A basic class that merges various zip files that
 * 	contain images and images maps to store determine
 *  which image is needed.  
 * 
 * @author R.Wisniewski1101
 */
public class ZipImageStore implements ImageStore {
	//the zip files
	private Map<ImageMap, ZipFileReader> files;
	//the images
	private Map<String, Map<String, Map<String, List<Image>>>> images;
	//the standard image
	private static final Object[] standard = {"luigibros.logic.Luigi", "default", "normal", 0};
	//the standard width;
	private int standardX = -1;
	//the standard height;
	private int standardY = -1;
	
	/** Creates a store with a default zip map combo.  
	 * 
	 * @param map
	 * @param zipFlie
	 */
	public ZipImageStore(ImageMap map, ZipFileReader zipFlie) {
		files = new HashMap<ImageMap, ZipFileReader>();
		if(map != null)
			files.put(map, zipFlie);
		images = new HashMap<String, Map<String, Map<String, List<Image>>>>();
	}
	/** Adds a zip map combo to this store
	 * 
	 * @param map
	 * @param zipFlie
	 */
	public void addSource(ImageMap map, ZipFileReader zipFlie) {
		if(map != null) {
			images.clear();
			files.put(map, zipFlie);
		}
	}
	@Override
	public boolean preload(String className, String stateName) throws IOException {
		LazyList<ImageMap> maps = new LazyList<ImageMap>(files.keySet());
		Map<String, ImageMap> actionNames = new HashMap<String, ImageMap>();
		for(ImageMap map : maps) {
			Map<String, Map<String, Map<String, List<SpriteRecord>>>> recordSet = map.getClassMap();
			Map<String, Map<String, List<SpriteRecord>>> states = recordSet.get(className);
			if(states != null) {
				Map<String, List<SpriteRecord>> actionSet = states.get(stateName);
				if(actionSet != null)
					for(String actionString : actionSet.keySet())
						actionNames.put(actionString, map);
			}
		}
		if(actionNames.keySet().size() == 0) return false;
		Map<String, Map<String, List<Image>>> states = images.get(className);
		if(states == null) {
			states = new HashMap<String, Map<String, List<Image>>>();
			images.put(className, states);
		}
		Map<String, List<Image>> actions = states.get(stateName);
		if(actions == null) {
			actions = new HashMap<String, List<Image>>();
			states.put(stateName, actions);
		}
		for(String actionName : actionNames.keySet()) {
			List<SpriteRecord> records = actionNames.get(actionName).getClassMap().get(className).get(stateName).get(actionName);
			List<Image> images = new LazyList<Image>(records.size());
			for(SpriteRecord record : records)
				images.add(record.frame(), files.get(actionNames.get(actionName)).getImage(record.path()));
			actions.put(actionName, images);
		}
		return true;
	}
	@Override
	public List<Image> loadImages(String className, String stateName, String actionName) {
		try{
			return images.get(className).get(stateName).get(actionName);
		} catch (NullPointerException e) {
			return null;
		}
	}

	@Override
	public int getStandardX() {
		return standardX;
	}

	@Override
	public int getStandardY() {
		return standardY;
	}
	/** Get the standard sizes from the zip file(s)
	 */
	public void loadStandard(ImageObserver observer) {
		try {
			preload((String)standard[0], (String)standard[1]);
			Image std = loadImages((String)standard[0], (String)standard[1], (String)standard[2]).get((Integer)standard[3]);
			standardX = std.getWidth(observer);
			standardY = std.getHeight(observer);
		} catch (IOException e) {
			throw new IllegalStateException("Standard image not found.  ");
		}
	}
}
